# -*- coding: utf-8 -*-
#
# The Philatelist program is a fork of the OpenNumismat program
# Copyright (c) 2011 - 2024 Vitaly Ignatov (OpenNumismat) <opennumismat@gmail.com>
# Copyright (c) 2021 - 2024 Victor Nabatov (Philatelist) <nabatov.victor@gmail.com>
#

import os.path
import sys

from PySide6.QtCore import Qt, QFileInfo, QProcess, QSettings, QTimer, QUrl
from PySide6.QtGui import QAction, QDesktopServices, QIcon, QKeySequence
from PySide6.QtWidgets import (
    QApplication, QDialog, QFileDialog, QLabel, QLineEdit, QMainWindow, QMenu,
    QMessageBox, QSizePolicy, QStyle, QToolBar, QToolButton, QWidget
)

import Philatelist
from Philatelist.Collection.Collection import Collection
from Philatelist.Collection.CollectionPages import CollectionPageTypes
from Philatelist.Collection.Description import DescriptionDialog
from Philatelist.Collection.Export.Json import ExportToJson
from Philatelist.Collection.Import import *
from Philatelist.Collection.Import.Colnect import ColnectDialog, colnectAvailable
from Philatelist.LatestCollections import LatestCollections
from Philatelist.Reports import Report
from Philatelist.Settings import Settings
from Philatelist.SettingsDialog import SettingsDialog
from Philatelist.SummaryDialog import SummaryDialog
from Philatelist.TabView import TabView
from Philatelist.TagsDialog import TagsDialog
from Philatelist.Tools.CursorDecorators import waitCursorDecorator
from Philatelist.Tools.MergeDatabases import MergeDatabases
from Philatelist.Tools.SynchronizeCollections import SynchronizeCollections
from Philatelist import version

class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowIcon(QIcon(':/main.ico'))
        self.createStatusBar()
        menubar = self.menuBar()

        self.collectionActs = []
        self.tableViewAct = QAction(
            QIcon(':/application_view_list.png'),
            self.tr("Table view"),
            self
        )
        self.tableViewAct.setData(CollectionPageTypes.List)
        self.tableViewAct.triggered.connect(self.changeViewEvent)
        self.collectionActs.append(self.tableViewAct)
        self.iconViewAct = QAction(
            QIcon(':/application_view_icons.png'),
            self.tr("Icon view"),
            self
        )
        self.iconViewAct.setData(CollectionPageTypes.Icon)
        self.iconViewAct.triggered.connect(self.changeViewEvent)
        self.collectionActs.append(self.iconViewAct)

        viewMenu = QMenu(self.tr("Change view"), self)
        viewMenu.addAction(self.tableViewAct)
        viewMenu.addAction(self.iconViewAct)

        self.viewButton = QToolButton()
        self.viewButton.setPopupMode(QToolButton.InstantPopup)
        self.viewButton.setMenu(viewMenu)
        self.viewButton.setDefaultAction(self.tableViewAct)

        colnectAct = QAction(QIcon(':/colnect.png'), "Colnect", self)
        colnectAct.triggered.connect(self.colnectEvent)
        self.collectionActs.append(colnectAct)

        self.detailsAct = QAction(QIcon(':/application-form.png'), self.tr("Info panel"), self)
        self.detailsAct.setCheckable(True)
        self.detailsAct.triggered.connect(self.detailsEvent)
        self.collectionActs.append(self.detailsAct)

        self.statisticsAct = QAction(QIcon(':/chart-bar.png'), self.tr("Statistics"), self)
        self.statisticsAct.setCheckable(True)
        self.statisticsAct.triggered.connect(self.statisticsEvent)
        self.collectionActs.append(self.statisticsAct)

        summaryAct = QAction(self.tr("Summary"), self)
        summaryAct.triggered.connect(self.summaryEvent)
        self.collectionActs.append(summaryAct)

        settingsAct = QAction(QIcon(':/cog.png'), self.tr("Settings..."), self)
        settingsAct.triggered.connect(self.settingsEvent)

        self.enableDragAct = QAction(
            QIcon(':/arrow_switch.png'),
            self.tr("Sort by drag-n-drop mode"),
            self
        )
        self.enableDragAct.setCheckable(True)
        self.enableDragAct.triggered.connect(self.enableDragEvent)
        self.collectionActs.append(self.enableDragAct)

        self.exitAct = QAction(QIcon(':/door_in.png'), self.tr("E&xit"), self)
        self.exitAct.setShortcut(QKeySequence.Quit)
        self.exitAct.triggered.connect(self.close)

        newCollectionAct = QAction(self.tr("&New..."), self)
        newCollectionAct.triggered.connect(self.newCollectionEvent)

        style = QApplication.style()
        icon = style.standardIcon(QStyle.SP_DialogOpenButton)
        openCollectionAct = QAction(icon, self.tr("&Open..."), self)
        openCollectionAct.setShortcut(QKeySequence.Open)
        openCollectionAct.triggered.connect(self.openCollectionEvent)

        closeCollectionAct = QAction(self.tr("&Close collection"), self)
        closeCollectionAct.triggered.connect(self.__closeCollection)

        backupCollectionAct = QAction(
            QIcon(':/database_backup.png'),
            self.tr("Backup"),
            self
        )
        backupCollectionAct.triggered.connect(self.backupCollectionEvent)
        self.collectionActs.append(backupCollectionAct)

        vacuumCollectionAct = QAction(QIcon(':/compress.png'), self.tr("Vacuum"), self)
        vacuumCollectionAct.triggered.connect(self.vacuumCollectionEvent)
        self.collectionActs.append(vacuumCollectionAct)

        descriptionCollectionAct = QAction(self.tr("Description"), self)
        descriptionCollectionAct.triggered.connect(self.descriptionCollectionEvent)
        self.collectionActs.append(descriptionCollectionAct)

        importMenu = QMenu(self.tr("Import"), self)
        self.collectionActs.append(importMenu)
        if ImportExcel.isAvailable():
            importExcelAct = QAction(QIcon(':/excel.png'), "Excel", self)
            importExcelAct.triggered.connect(self.importExcel)
            self.collectionActs.append(importExcelAct)
            importMenu.addAction(importExcelAct)

        if ImportColnect.isAvailable():
            importColnectAct = QAction(QIcon(':/colnect.png'), "Colnect", self)
            importColnectAct.triggered.connect(self.importColnect)
            self.collectionActs.append(importColnectAct)
            importMenu.addAction(importColnectAct)

        if ImportTellico.isAvailable():
            importTellicoAct = QAction(QIcon(':/tellico.png'), "Tellico", self)
            importTellicoAct.triggered.connect(self.importTellico)
            self.collectionActs.append(importTellicoAct)
            importMenu.addAction(importTellicoAct)

        importJsonAct = QAction(QIcon(':/json.png'), "JSON", self)
        importJsonAct.triggered.connect(self.importJson)
        self.collectionActs.append(importJsonAct)
        importMenu.addAction(importJsonAct)

        synchronizeCollectionsAct = QAction(QIcon(':/refresh.png'), self.tr("Synchronization..."), self)
        synchronizeCollectionsAct.triggered.connect(self.synchronizeCollectionsEvent)
        self.collectionActs.append(synchronizeCollectionsAct)

        mergeCollectionAct = QAction(QIcon(':/refresh.png'), self.tr("Merge..."), self)
        mergeCollectionAct.triggered.connect(self.mergeCollectionEvent)
        self.collectionActs.append(mergeCollectionAct)

        exportMenu = QMenu(self.tr("Export"), self)
        self.collectionActs.append(exportMenu)

        exportJsonAct = QAction(QIcon(':/json.png'), "JSON", self)
        exportJsonAct.triggered.connect(self.exportJson)
        self.collectionActs.append(exportJsonAct)
        exportMenu.addAction(exportJsonAct)

        file = menubar.addMenu(self.tr("&Collection"))

        file.addAction(newCollectionAct)
        file.addAction(openCollectionAct)
        file.addAction(closeCollectionAct)
        file.addSeparator()
        file.addAction(backupCollectionAct)
        file.addAction(vacuumCollectionAct)
        file.addAction(descriptionCollectionAct)
        file.addSeparator()
        file.addMenu(importMenu)
        file.addMenu(exportMenu)
        file.addAction(synchronizeCollectionsAct)
        file.addAction(mergeCollectionAct)
        file.addSeparator()

        self.latestActions = []
        self.__updateLatest(file)

        file.addAction(settingsAct)
        file.addSeparator()

        file.addAction(self.exitAct)

        addStampAct = QAction(QIcon(':/add.png'), self.tr("Add"), self)
        addStampAct.setShortcut(Qt.Key_Insert)
        addStampAct.triggered.connect(self.addStamp)
        self.collectionActs.append(addStampAct)

        editStampAct = QAction(QIcon(':/pencil.png'), self.tr("Edit..."), self)
        editStampAct.triggered.connect(self.editStamp)
        self.collectionActs.append(editStampAct)

        style = QApplication.style()
        icon = style.standardIcon(QStyle.SP_TrashIcon)
        deleteStampAct = QAction(icon, self.tr("Delete"), self)
        deleteStampAct.setShortcut(QKeySequence.Delete)
        deleteStampAct.triggered.connect(self.deleteStamp)
        self.collectionActs.append(deleteStampAct)

        copyStampAct = QAction(QIcon(':/page_copy.png'), self.tr("Copy"), self)
        copyStampAct.setShortcut(QKeySequence.Copy)
        copyStampAct.triggered.connect(self.copyStamp)
        self.collectionActs.append(copyStampAct)

        pasteStampAct = QAction(QIcon(':/page_paste.png'), self.tr("Paste"), self)
        pasteStampAct.setShortcut(QKeySequence.Paste)
        pasteStampAct.triggered.connect(self.pasteStamp)
        self.collectionActs.append(pasteStampAct)

        record = menubar.addMenu(self.tr("Record"))
        self.collectionActs.append(record)
        record.addAction(addStampAct)
        record.addAction(editStampAct)
        record.addSeparator()
        if colnectAvailable:
            record.addAction(colnectAct)

        record.addSeparator()
        record.addAction(copyStampAct)
        record.addAction(pasteStampAct)
        record.addSeparator()
        record.addAction(deleteStampAct)

        detailsMenu = QMenu(self.tr("Details"), self)
        detailsMenu.addAction(self.detailsAct)
        detailsMenu.addAction(self.statisticsAct)

        view = menubar.addMenu(self.tr("&View"))
        self.collectionActs.append(view)
        view.addMenu(detailsMenu)
        view.addMenu(viewMenu)

        viewBrowserAct = QAction(
            QIcon(':/page_white_world.png'),
            self.tr("View in browser"),
            self
        )
        viewBrowserAct.triggered.connect(self.viewBrowserEvent)
        self.collectionActs.append(viewBrowserAct)

        self.viewTab = TabView(self)

        actions = self.viewTab.actions()
        listMenu = menubar.addMenu(self.tr("List"))
        listMenu.addAction(actions['new'])
        listMenu.addMenu(actions['open'])
        listMenu.aboutToShow.connect(self.viewTab.updateOpenPageMenu)
        listMenu.addAction(actions['rename'])
        listMenu.addSeparator()
        listMenu.addAction(actions['select'])
        listMenu.addAction(actions['customize_tree'])
        listMenu.addSeparator()
        listMenu.addAction(actions['cancel_filtering'])
        self.collectionActs.append(actions['cancel_filtering'])
        listMenu.addAction(actions['cancel_sorting'])
        self.collectionActs.append(actions['cancel_sorting'])
        listMenu.addAction(actions['save_sorting'])
        self.collectionActs.append(actions['save_sorting'])
        listMenu.addSeparator()
        listMenu.addAction(actions['close'])
        listMenu.addAction(actions['remove'])
        self.collectionActs.append(listMenu)

        self.referenceMenu = menubar.addMenu(self.tr("Reference"))
        self.collectionActs.append(self.referenceMenu)

        self.tagsAct = QAction(self.tr("Tags..."), self)
        self.tagsAct.triggered.connect(self.tagsEvent)

        reportAct = QAction(self.tr("Report..."), self)
        reportAct.setShortcut(QKeySequence.Print)
        reportAct.triggered.connect(self.report)
        self.collectionActs.append(reportAct)

        saveTableAct = QAction(QIcon(':/table.png'), self.tr("Save current list..."), self)
        saveTableAct.triggered.connect(self.saveTable)
        self.collectionActs.append(saveTableAct)

        report = menubar.addMenu(self.tr("Report"))
        self.collectionActs.append(report)
        report.addAction(reportAct)
        report.addAction(saveTableAct)
        default_template = Settings()['template']
        viewBrowserMenu = report.addMenu(QIcon(':/page_white_world.png'), self.tr("View in browser"))
        for template in Report.scanTemplates():
            act = QAction(template[0], self)
            act.setData(template[1])
            act.triggered.connect(self.viewBrowserEvent)
            viewBrowserMenu.addAction(act)
            if default_template == template[1]:
                viewBrowserMenu.setDefaultAction(act)

        self.collectionActs.append(exportMenu)
        report.addSeparator()
        report.addAction(summaryAct)

        referencesGeneratorAct = QAction(self.tr("References generator"), self)
        referencesGeneratorAct.triggered.connect(self.referencesGenerator)

        tools = menubar.addMenu(self.tr("Tools"))
        tools.addAction(referencesGeneratorAct)

        helpAct = QAction(QIcon(':/help.png'), self.tr("User manual"), self)
        helpAct.setShortcut(QKeySequence.HelpContents)
        helpAct.triggered.connect(self.onlineHelp)
        webAct = QAction(self.tr("Visit web-site"), self)
        webAct.triggered.connect(self.visitWeb)
        aboutAct = QAction(self.tr("About %s") % version.AppName, self)
        aboutAct.triggered.connect(self.about)

        help_ = menubar.addMenu(self.tr("&Help"))
        help_.addAction(helpAct)
        help_.addAction(webAct)
        help_.addSeparator()
        help_.addAction(aboutAct)

        toolBar = QToolBar(self.tr("Toolbar"), self)
        toolBar.setObjectName("Toolbar")
        toolBar.setMovable(False)
        toolBar.addAction(openCollectionAct)
        toolBar.addSeparator()
        toolBar.addAction(addStampAct)
        toolBar.addAction(editStampAct)
        toolBar.addAction(viewBrowserAct)
        toolBar.addSeparator()
        toolBar.addAction(actions['cancel_filtering'])
        toolBar.addAction(actions['cancel_sorting'])
        toolBar.addAction(actions['save_sorting'])
        toolBar.addAction(self.enableDragAct)
        toolBar.addSeparator()
        toolBar.addAction(settingsAct)
        toolBar.addSeparator()
        toolBar.addAction(self.detailsAct)
        toolBar.addAction(self.statisticsAct)
        if colnectAvailable:
            toolBar.addSeparator()
            toolBar.addAction(colnectAct)

        toolBar.addSeparator()
        toolBar.addWidget(self.viewButton)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        toolBar.addWidget(spacer)

        self.quickSearch = QLineEdit()
        self.quickSearch.setMaximumWidth(250)
        self.quickSearch.setClearButtonEnabled(True)
        self.quickSearch.setPlaceholderText(self.tr("Quick search"))
        self.quickSearch.textEdited.connect(self.quickSearchEdited)
        self.collectionActs.append(self.quickSearch)
        self.quickSearchTimer = QTimer(self)
        self.quickSearchTimer.setSingleShot(True)
        self.quickSearchTimer.timeout.connect(self.quickSearchClicked)
        toolBar.addWidget(self.quickSearch)

        self.addToolBar(toolBar)
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.setWindowTitle(version.AppName)

        settings = QSettings()
        geometry = settings.value('mainwindow/geometry')
        if geometry:
            self.restoreGeometry(geometry)

        winState = settings.value('mainwindow/winState')
        if winState:
            self.restoreState(winState)

    def openStartCollection(self):
        if len(sys.argv) > 1:
            fileName = sys.argv[1]
        else:
            latest = LatestCollections(self)
            fileName = latest.latest()

        self.collection = Collection(self)
        self.openCollection(fileName)
        self.setCentralWidget(self.viewTab)

    def createStatusBar(self):
        self.collectionFileLabel = QLabel()
        self.statusBar().addWidget(self.collectionFileLabel)

    def __updateLatest(self, menu=None):
        if menu:
            self.__menu = menu

        for act in self.latestActions:
            self.__menu.removeAction(act)

        self.latestActions = []
        latest = LatestCollections(self)
        for act in latest.actions():
            self.latestActions.append(act)
            act.triggered.connect(self.openLatestCollectionEvent)
            self.__menu.insertAction(self.exitAct, act)

        self.__menu.insertSeparator(self.exitAct)

    def enableDragEvent(self):
        listView = self.viewTab.currentListView()
        if self.enableDragAct.isChecked():
            res = listView.tryDragMode()
            self.enableDragAct.setChecked(res)
        else:
            self.enableDragAct.setChecked(False)
            listView.selectMode()

    def settingsEvent(self):
        dialog = SettingsDialog(self.collection, self)
        res = dialog.exec_()
        if res == QDialog.Accepted:
            result = QMessageBox.question(
                self,
                self.tr("Settings"),
                self.tr("The application needs to be restarted"),
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes
            )
            if result == QMessageBox.Yes:
                self.restart()

        dialog.deleteLater()

    def changeViewEvent(self):
        type_ = self.sender().data()
        page = self.viewTab.currentPageView().param
        self.viewTab.collection.pages().changeView(page, type_)
        self.viewTab.clearStatusBar()
        page = self.viewTab.currentPageView()
        page.changeView(type_)
        self.viewTab.updatePage(page)

    def colnectEvent(self):
        model = self.viewTab.currentModel()
        dialog = ColnectDialog(model, self)
        dialog.exec_()
        dialog.deleteLater()

    def updateInfoType(self, info_type):
        self.detailsAct.setChecked(False)
        self.statisticsAct.setChecked(False)
        if info_type == CollectionPageTypes.Statistics:
            self.statisticsAct.setChecked(True)
        else:
            self.detailsAct.setChecked(True)

    def detailsEvent(self, checked):
        self.updateInfoType(CollectionPageTypes.Details)
        if checked:
            page = self.viewTab.currentPageView()
            self.collection.pages().changeInfoType(page.param, CollectionPageTypes.Details)
            page.showInfo(CollectionPageTypes.Details)

    def statisticsEvent(self, checked):
        self.updateInfoType(CollectionPageTypes.Statistics)
        if checked:
            page = self.viewTab.currentPageView()
            self.collection.pages().changeInfoType(page.param, CollectionPageTypes.Statistics)
            page.showInfo(CollectionPageTypes.Statistics)

    def summaryEvent(self):
        model = self.viewTab.currentModel()
        dialog = SummaryDialog(model, self)
        dialog.exec_()
        dialog.deleteLater()

    def tagsEvent(self):
        model = self.viewTab.currentModel()
        dialog = TagsDialog(model.database(), self)
        res = dialog.exec_()
        if res == QDialog.Accepted:
            model.tagsChanged.emit()

        dialog.deleteLater()

    def restart(self):
        self.close()
        program = sys.executable
        argv = []
        if "__compiled__" in globals():
            # Process running as Nuitka
            program = sys.argv[0]

        elif program != sys.argv[0] and "__compiled__" not in globals():
            # Process running as Python arg
            argv.append(sys.argv[0])

        QProcess.startDetached(program, argv)

    def importTellico(self):
        defaultDir = ImportTellico.defaultDir()
        file, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Select file"),
            defaultDir,
            "*.tc"
        )
        if file:
            imp = ImportTellico(self)
            imp.importData(file, self.viewTab.currentModel())

    def importExcel(self):
        defaultDir = ImportExcel.defaultDir()
        file, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Select file"),
            defaultDir,
            "*.xlsx"
        )
        if file:
            imp = ImportExcel(self)
            imp.importData(file, self.viewTab.currentModel())

    def importColnect(self):
        defaultDir = ImportColnect.defaultDir()
        file, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Select file"),
            defaultDir,
            "*.csv"
        )
        if file:
            imp = ImportColnect(self)
            imp.importData(file, self.viewTab.currentModel())

    def exportJson(self):
        self.export = ExportToJson(self.collection)
        self.export.exportToJson()

    def importJson(self):
        self.import_json = ImportFromJson(self.collection)
        self.import_json.jsonReadData(self.__workingDir())

    def addStamp(self):
        model = self.viewTab.currentModel()
        model.addStamp(model.record(), self)

    def editStamp(self):
        listView = self.viewTab.currentListView()
        indexes = listView.selectedStamps()
        if len(indexes) == 1:
            listView._edit(indexes[0])

        elif len(indexes) > 1:
            listView._multiEdit(indexes)

    def deleteStamp(self):
        listView = self.viewTab.currentListView()
        indexes = listView.selectedStamps()
        if len(indexes):
            listView._delete(indexes)

    def copyStamp(self):
        listView = self.viewTab.currentListView()
        indexes = listView.selectedStamps()
        if len(indexes):
            listView._copy(indexes)

    def pasteStamp(self):
        listView = self.viewTab.currentListView()
        listView._paste()

    def quickSearchEdited(self, _text):
        self.quickSearchTimer.start(180)

    def quickSearchClicked(self):
        listView = self.viewTab.currentListView()
        listView.search(self.quickSearch.text())

    def viewBrowserEvent(self):
        template = self.sender().data()
        listView = self.viewTab.currentListView()
        listView.viewInBrowser(template)

    def report(self):
        listView = self.viewTab.currentListView()
        listView.report()

    def saveTable(self):
        listView = self.viewTab.currentListView()
        listView.saveTable()

    def __workingDir(self):
        fileName = self.collection.fileName
        if not fileName:
            fileName = LatestCollections.DefaultCollectionName

        return QFileInfo(fileName).absolutePath()

    def openCollectionEvent(self):
        fileName, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Open collection"),
            self.__workingDir(),
            self.tr("Collections (*.db)")
        )
        if fileName:
            self.openCollection(fileName)

    def newCollectionEvent(self):
        fileName, _selectedFilter = QFileDialog.getSaveFileName(
            self,
            self.tr("New collection"),
            self.__workingDir(),
            self.tr("Collections (*.db)"),
            "",
            QFileDialog.DontConfirmOverwrite
        )
        if fileName:
            self.__closeCollection()
            if self.collection.create(fileName):
                self.setCollection(self.collection)
                dialog = SettingsDialog(self.collection)
                result = dialog.exec_()
                if result == QDialog.Accepted:
                    self.restart()

                dialog.deleteLater()

    def descriptionCollectionEvent(self):
        dialog = DescriptionDialog(self.collection.getDescription(), self)
        dialog.exec_()
        dialog.deleteLater()

    def backupCollectionEvent(self):
        self.collection.backup()

    def vacuumCollectionEvent(self):
        # Fetch all List models before vacuum
        for i in range(self.viewTab.count()):
            listView = self.viewTab.widget(i)
            listView.modelChanged()

        self.collection.vacuum()

    def synchronizeCollectionsEvent(self):
        file_name, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Open collection"),
            self.__workingDir(),
            self.tr("Collections (*.db)")
        )
        if file_name:
            synchronize = SynchronizeCollections(self.collection)
            synchronize.synchronize(file_name)

    def mergeCollectionEvent(self):
        file_name, _selectedFilter = QFileDialog.getOpenFileName(
            self,
            self.tr("Open collection"),
            self.__workingDir(),
            self.tr("Collections (*.db)")
        )
        if file_name:
            merge = MergeDatabases(self.collection)
            merge.merge(file_name)

    def openCollection(self, fileName):
        self.__closeCollection()
        if self.collection.open(fileName):
            self.setCollection(self.collection)
        else:
            # Remove wrong collection from latest collections list
            latest = LatestCollections(self)
            latest.delete(fileName)
            self.__updateLatest()

    def openLatestCollectionEvent(self):
        fileName = self.sender().data()
        self.openCollection(fileName)

    @waitCursorDecorator
    def setCollection(self, collection):
        self.collection.loadReference(Settings()['reference'])
        self.__setEnabledActs(True)
        self.collectionFileLabel.setText(collection.getFileName())
        title = f"{collection.getCollectionName()}"
        self.setWindowTitle(title)

        latest = LatestCollections(self)
        latest.add(collection.getFileName())
        self.__updateLatest()
        self.viewTab.setCollection(collection)
        self.referenceMenu.clear()
        if collection.settings['tags_used']:
            self.referenceMenu.addAction(self.tagsAct)
            self.referenceMenu.addSeparator()

        for action in self.collection.referenceMenu(self):
            self.referenceMenu.addAction(action)

        if os.path.exists(collection.settings['store']):
            if collection.settings['store'] != Philatelist.IMAGES_PATH:
                Philatelist.IMAGES_PATH = collection.settings['store']
        else:
            QMessageBox.critical(
                collection.parent(),
                self.tr("Open collection"),
                self.tr("Image storage %s for the %s collection not exists") % (collection.settings['store'], title)
            )
            self.__closeCollection()

    def __setEnabledActs(self, enabled):
        for act in self.collectionActs:
            act.setEnabled(enabled)

    def __closeCollection(self):
        self.__saveParams()
        self.__setEnabledActs(False)
        self.viewTab.clear()
        self.referenceMenu.clear()
        self.quickSearch.clear()
        self.collectionFileLabel.setText(
            self.tr("Create new collection or open one of the existing")
        )
        self.setWindowTitle(version.AppName)

    def closeEvent(self, e):
        self.__shutDown()

    def __shutDown(self):
        self.__saveParams()
        settings = QSettings()
        # Save main window size
        settings.setValue('mainwindow/geometry', self.saveGeometry())
        settings.setValue('mainwindow/winState', self.saveState())

    def __saveParams(self):
        if self.collection.isOpen():
            for param in self.collection.pages().pagesParam():
                param.listParam.save_lists(only_if_changed=True)

            self.viewTab.savePagePositions(only_if_changed=True)
            if Settings()['autobackup']:
                if self.collection.isNeedBackup():
                    self.collection.backup()

    def referencesGenerator(self):
        self._openUrl("https://opennumismat.github.io/references/")

    def about(self):
        QMessageBox.about(
            self,
            self.tr("About %s") % version.AppName,
            "%s %s\n\n" % (version.AppName, version.Version) +
            self.tr("Copyright (C) 2011-2024 Vitaly Ignatov\n") +
            self.tr("Copyright (C) 2022-2024 Victor Nabatov\n\n") +
            self.tr("%s - is freeware, open source\nand licensed under a GPLv3.") % version.AppName
        )

    def onlineHelp(self):
        self._openUrl("https://opennumismat.github.io/open-numismat/manual.html")

    def visitWeb(self):
        self._openUrl(version.Web)

    def _openUrl(self, url):
        executor = QDesktopServices()
        executor.openUrl(QUrl(url))
